﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace exercice4
    {
    class MyMath
        {
        /// <summary>
        /// Permet de calculer la racine d'un nombre entier sans utiliser Math.Sqrt
        /// </summary>
        /// <param name="a">Le nombre dont on cherche la racine</param>
        /// <param name="p">La précision de la recherche (par défaut à 10^-9)</param>
        /// <param name="isVerbose">Affichage des valeurs intermédiaires et du récapitulatif</param>
        /// <returns>La racine de 'a'</returns>
        public static double sqrt(double a, double p=MyMath.DEFAULT_SQRT_PRECISION, bool isVerbose=false)
            {
            try
                {
                if (a < 0) { throw new Exception("Sqrt of a negative number is not possible in real set !"); }
    
                double x = a;
                int nbIteration = 0;
                double limit = a * p;

                DateTime t1 = DateTime.Now;
                do
                    {
                    x = MyMath.algoSqrt(a, x);
                    if (isVerbose)
                        {
                        System.Console.WriteLine("square root approximation of {0:f} is {1:f}", a, x);
                        }
                    ++nbIteration;
                    } while (x * x + limit < a || x * x - limit > a);
                DateTime t2 = DateTime.Now;
           
                if (isVerbose)
                    {
                    System.Console.WriteLine("The number of iterations : {0:n}", nbIteration);
                    System.Console.WriteLine("Elapsed time in ms : {0:n}", t2.Millisecond - t1.Millisecond);
                    System.Console.WriteLine("Residual error  : {0:f12}", Math.Abs(Math.Sqrt(a) - x));
                    }

                return x;
                }
            catch (Exception e)
                {
                System.Console.WriteLine(e.Message);
                return Double.NaN;
                }
            }

        private static double algoSqrt(double a, double x)
            {
            if (a == 0) { return 0; }
            return (x + a / x) / 2;
            }

        public const double DEFAULT_SQRT_PRECISION = 1e-9;
        }
    }
